package edu.hznu.retroSnakerPlanServer.worker;


import edu.hznu.retroSnakerPlanServer.runner.FoodMaintenanceRunner;
import edu.hznu.retroSnakerPlanServer.runner.MessageProcessRunner;
import edu.hznu.retroSnakerPlanServer.runner.PlayerMaintenaceRunner;
import edu.hznu.retroSnakerPlanServer.utils.ByteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * create by Cliven on 2018-06-01 21:31
 *
 * @author Cliven
 * 负责UPD 服务器的端口监听等操作
 */
public class UDPWorker {
    private static final Logger log = LoggerFactory.getLogger(UDPWorker.class);
    private Integer port;
    // 线程池构造对象
    private  ExecutorService singleThreadExecutor;

    public UDPWorker() {
        this.port = 8086;
    }

    public UDPWorker(Integer port) {
        this.port = port;
    }

    /**
     * 初始化函数
     */
    private void init(){
        // 创建缓存线程池线程池
        singleThreadExecutor = Executors.newCachedThreadPool();
        // 把食物维护线程加入线程池中
        singleThreadExecutor.execute(new FoodMaintenanceRunner());
        // 把玩家维护线程加入线程池中
        singleThreadExecutor.execute(new PlayerMaintenaceRunner());
    }


    public void run() {
        log.info("Start server...");
        DatagramSocket datagramSocket = null;

        try {
            byte[] buf = new byte[1024];
            // 监听3000端口
            datagramSocket = new DatagramSocket(port);
            // 打包收到消息的
            DatagramPacket receivedDatagramPacket = new DatagramPacket(buf, buf.length);
            // 初始化线程池和地图信息
            init();
            log.info("Start to receive message...");
            while (true) {
                // 从监听端口接收数据，该方法会导致线程阻塞
                datagramSocket.receive(receivedDatagramPacket);
                log.debug("Recv msg!");
                log.debug("{}",ByteUtils.bytesToHex(receivedDatagramPacket.getData(),0,receivedDatagramPacket.getLength()));
                // 将消息交给新的线程处理
//                new MessageProcessRunner(datagramSocket, receivedDatagramPacket).run();
                singleThreadExecutor.execute(new MessageProcessRunner(datagramSocket, receivedDatagramPacket));
                //由于receivedDatagramPacket在接收了数据之后，其内部消息长度值会变为实际接收的消息的字节数，
                //所以这里要将dp_receive的内部消息长度重新置为1024
                receivedDatagramPacket.setLength(buf.length);
            }
        } catch (Exception e) {
            log.error("Server IO Exception：", e);
        } finally {
            if (datagramSocket != null) {
                datagramSocket.close();
            }
            singleThreadExecutor.shutdown();
        }
    }
}
